package com.rm.zeyou.util.http;

import com.alibaba.fastjson.JSON;
import com.rm.zeyou.config.resttemple.RestTemplateUtil;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author zlx
 * @create: 2021-03-14
 */
@Component
@Slf4j
public class HttpClientUtil {

    // @Resource
    // private RestTemplateUtil restTemplate;
    /**
     * 保存微信平台证书
     */
    private final ConcurrentHashMap<String, AutoUpdateCertificatesVerifier> verifierMap = new ConcurrentHashMap<>();

    /**
     * get请求
     *
     * @param url          地址
     * @param uriVariables URI参数
     */
    public String doGet(@NotNull String url,
                        Map<String, String> paramMap,
                        Object... uriVariables) {
        return doGet(url, paramMap, String.class, null, uriVariables);
    }

    /**
     * 不需要Header GET请求
     *
     * @param url          地址
     * @param paramMap     参数
     * @param responseType response类型
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doGet(@NotNull String url,
                       Map<String, String> paramMap,
                       @NotNull Class<T> responseType,
                       Object... uriVariables) {
        return doGet(url, paramMap, responseType, null, uriVariables);
    }

    /**
     * GET请求
     *
     * @param url          地址
     * @param paramMap     参数
     * @param responseType response类型
     * @param headerMap    Header
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doGet(@NotNull String url,
                       Map<String, String> paramMap,
                       @NotNull Class<T> responseType,
                       Map<String, String> headerMap,
                       Object... uriVariables) {
        return doMethod(url, null, paramMap, responseType, headerMap, HttpMethod.GET, uriVariables);
    }

    /**
     * 不需要Header POST
     *
     * @param url          地址
     * @param object       BODY
     * @param responseType response类型
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doPost(@NotNull String url,
                        Object object,
                        Map<String, String> paramMap,
                        @NotNull Class<T> responseType,
                        Object... uriVariables) {

        return doPost(url, object, paramMap, responseType, null, uriVariables);
    }

    /**
     * POST
     *
     * @param url          地址
     * @param object       BODY
     * @param paramMap     Parameters
     * @param responseType response类型
     * @param headerMap    Header
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doPost(@NotNull String url,
                        Object object,
                        Map<String, String> paramMap,
                        @NotNull Class<T> responseType,
                        Map<String, String> headerMap,
                        Object... uriVariables) {

        return doMethod(url, object, paramMap, responseType, headerMap, HttpMethod.POST, uriVariables);
    }

    /**
     * 不需要Header PUT请求
     *
     * @param url          地址
     * @param object       BODY
     * @param paramMap     Parameters
     * @param responseType response类型
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doPut(@NotNull String url,
                       Object object,
                       Map<String, String> paramMap,
                       @NotNull Class<T> responseType,
                       Object... uriVariables) {

        return doPut(url, object, paramMap, responseType, null, uriVariables);

    }

    /**
     * PUT请求
     *
     * @param url          地址
     * @param object       BODY
     * @param paramMap     Parameters
     * @param responseType response类型
     * @param headerMap    Header
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doPut(@NotNull String url,
                       Object object,
                       Map<String, String> paramMap,
                       @NotNull Class<T> responseType,
                       Map<String, String> headerMap,
                       Object... uriVariables) {
        return doMethod(url, object, paramMap, responseType, headerMap, HttpMethod.PUT, uriVariables);
    }

    /**
     * DELETE 请求
     *
     * @param url
     * @param responseType response类型
     * @param paramMap     Parameters
     * @param headerMap    Header
     * @param uriVariables URI参数
     * @param <T>
     */
    public <T> T doDelete(@NotNull String url,
                          @NotNull Class<T> responseType,
                          Map<String, String> paramMap,
                          Map<String, String> headerMap,
                          Object... uriVariables) {
        return doMethod(url, null, paramMap, responseType, headerMap, HttpMethod.DELETE, uriVariables);
    }

    /**
     * @param url          地址
     * @param object       BODY
     * @param responseType response类型
     * @param headerMap    Header
     * @param method       Http方法
     * @param uriVariables URI参数
     * @param <T>          responseType实体
     */
    public <T> T doMethod(@NotNull String url,
                          Object object,
                          Map<String, ?> paramMap,
                          @NotNull Class<T> responseType,
                          Map<String, String> headerMap,
                          HttpMethod method,
                          Object... uriVariables) {

        HttpEntity<Object> httpEntity = this.createHttpEntity(object, headerMap);
        System.out.println(JSON.toJSONString(object,true));
        // 出现异常打印响应body处理
        RestTemplate restTemplate = RestTemplateUtil.getInstance();
        // RestTemplate instance = RestTemplateUtil.getInstance();
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        url = getUrlParamsByMap(url, paramMap);
        // 发出请求:
        ResponseEntity<T> responseEntity = null;
        try {
            responseEntity = restTemplate.exchange(url, method, httpEntity, responseType, uriVariables);

        } catch (RestClientException e) {
            throw new RuntimeException(e);
        }
        return this.getEntityFromHttpResponse(responseEntity);
    }

    /**
     * Map转url参数
     *
     * @param url
     * @param map
     */
    private String getUrlParamsByMap(String url, Map<String, ?> map) {
        if (map == null || map.size() < 1) {
            return url;
        }
        StringBuilder stringBuffer = new StringBuilder();
        stringBuffer.append(url);
        String wenHao = "?";
        String yuMark = "&";
        if (url.contains(wenHao)) {
            stringBuffer.append(yuMark);
        } else {
            stringBuffer.append(wenHao);
        }
        for (Map.Entry<String, ?> entry : map.entrySet()) {
            stringBuffer.append(entry.getKey()).append("=").append(entry.getValue());
            stringBuffer.append(yuMark);
        }
        String str = stringBuffer.toString();
        if (str.endsWith(yuMark)) {
            str = StringUtils.substringBeforeLast(str, yuMark);
        }
        return str;
    }

    /**
     * 说明：
     * 创建HTTP请求实体（header + entity）
     *
     * @param body
     * @param headerMap
     */
    private <T> HttpEntity<Object> createHttpEntity(T body, Map<String, String> headerMap) {
        // 1. 生成Http Header:
        HttpHeaders headers = createHttpHeaders(headerMap);
        return new HttpEntity<>(body, headers);
    }

    /**
     * 创建 Header
     *
     * @param headerMap
     */
    private HttpHeaders createHttpHeaders(Map<String, String> headerMap) {
        HttpHeaders headers = new HttpHeaders();
        if (null != headerMap) {
            headerMap.forEach(headers::set);
        }
        return headers;
    }

    /**
     * @param responseEntity
     * @param <T>
     */
    private <T> T getEntityFromHttpResponse(ResponseEntity<T> responseEntity) {
        // 3.提取用户信息:
        if (responseEntity.getStatusCodeValue() != HttpStatus.OK.value()) {
            throw new RuntimeException(Objects.requireNonNull(responseEntity.getBody()).toString());
        }
        return responseEntity.getBody();
    }
    public static String jsonPost(String url,String param){
        //申请一个请求头
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        RestTemplate restTemplate = new RestTemplate();
        //发送请求
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, param, String.class);
        return  responseEntity.getBody();
    }
    /**
     * 将通知参数转化为字符串
     * @param request
     * @return
     */
    public static String readData(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder result = new StringBuilder();
            br = request.getReader();
            for (String line; (line = br.readLine()) != null; ) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }
            return result.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


}